package io.gitee.zhucan123.core.infrastructure.dataconversion;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.ObjectReader;
import com.fasterxml.jackson.databind.ObjectWriter;
import com.fasterxml.jackson.databind.SerializationFeature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import javax.persistence.AttributeConverter;
import java.io.IOException;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.Collection;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @Auther: zlw
 * @Date: 2019/11/22 09:57
 * @Description:
 */
public class AbstractBaseListJsonConverter<T> implements AttributeConverter<List<T>, String> {
    protected static ObjectMapper objectMapper;

    @Autowired
    public void setObjectMapper(ObjectMapper objectMapper) {
        AbstractBaseListJsonConverter.objectMapper = objectMapper;
    }

    @Override
    public String convertToDatabaseColumn(List<T> attribute) {
        if(CollectionUtils.isEmpty(attribute)){
            return null;
        }
        objectMapper.setConfig(objectMapper.getSerializationConfig().without(SerializationFeature.FAIL_ON_EMPTY_BEANS));
        ObjectWriter writerCollection = objectMapper.writerFor(List.class);
        ObjectWriter writer = objectMapper.writerFor(getJsonType());
        try {
            return writerCollection.writeValueAsString(attribute.parallelStream().map(x -> {
                try {
                    return writer.writeValueAsString(x);
                } catch (JsonProcessingException e) {
                    e.printStackTrace();
                }
                return null;
            }).filter(x -> x!=null).collect(Collectors.toList()));
        } catch (JsonProcessingException e) {
            e.printStackTrace();
            return null;
        }
    }

    @Override
    public List<T> convertToEntityAttribute(String dbData) {
        if(StringUtils.isEmpty(dbData)){
            return null;
        }
        ObjectReader reader = objectMapper.readerFor(getJsonType());
        ObjectReader readerCollection = objectMapper.readerFor(Collection.class);
        try {
            return ((List<String>)readerCollection.readValue(dbData)).parallelStream().map(x -> {
                try {
                    return (T) reader.readValue(x);
                } catch (IOException e) {
                    e.printStackTrace();
                }
                return null;
            }).filter(x -> x!=null).collect(Collectors.toList());
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 获取子类中 json 转换的 TypeReference
     *
     * @return
     */
    protected TypeReference<T> getJsonType() {
        Type[] actualTypeArguments = ((ParameterizedType) (getClass().getGenericSuperclass())).getActualTypeArguments();
        if (actualTypeArguments != null && actualTypeArguments.length > 0) {
            return new TypeReference<T>() {
                @Override
                public Type getType() {
                    return actualTypeArguments[0];
                }

            };
        }

        return null;
    }
}
